fix(test-helpers): load the C runtime portably instead of hard-coding libc.so.6 - #2562
Open
LeSingh1 wants to merge 1 commit into
Open
fix(test-helpers): load the C runtime portably instead of hard-coding libc.so.6#2562LeSingh1 wants to merge 1 commit into
LeSingh1 wants to merge 1 commit into
Conversation
… libc.so.6
cuda_python_test_helpers/__init__.py loads the C runtime at import time:
if IS_WINDOWS:
libc = ctypes.CDLL("msvcrt.dll")
else:
libc = ctypes.CDLL("libc.so.6")
`libc.so.6` is the glibc soname specifically. It does not exist on musl
(Alpine) or on macOS, so importing the package raises OSError there:
OSError: dlopen(libc.so.6, 0x0006): tried: 'libc.so.6' (no such file), ...
Three things make that worse than it looks:
* The module computes IS_LINUX correctly four lines above and then does not
use it for this gate -- the else branch covers every non-Windows platform,
not Linux.
* The library is needed by exactly one function: memcmp, used by
cuda_core/tests/helpers/buffers.py. Everything else in the package
(IS_WSL, IS_LINUX, under_compute_sanitizer, driver_version_less_than) is
pure Python.
* The package is registered as a pytest plugin by cuda_core/tests/conftest.py
via pytest_plugins, so the failure stops the whole suite from being
*collected*, including every test that never touches libc.
Try the glibc soname first, so the library resolved on the platforms CI runs
on is unchanged, and fall back to ctypes.util.find_library("c"). If nothing
loads, raise an OSError naming the platform and what was tried instead of a
raw dlopen dump.
Note the package declares "Operating System :: POSIX :: Linux", so this is
arguably out of contract on macOS. It is not on musl, which is Linux and has
no libc.so.6 either -- and the cost of the current behaviour is that the
suite cannot be collected at all rather than skipping the one helper that
needs a C runtime.
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
cuda_python_test_helpers/__init__.pyloads the C runtime at import time:libc.so.6is the glibc soname specifically — it does not exist on musl or macOS:>>> import cuda_python_test_helpers OSError: dlopen(libc.so.6, 0x0006): tried: 'libc.so.6' (no such file), '/System/Volumes/Preboot/Cryptexes/OSlibc.so.6' (no such file), '/usr/lib/libc.so.6' (no such file, not in dyld cache), 'libc.so.6' (no such file)Three things make that more expensive than it first looks.
1. The file already computes the right predicate and does not use it. Four lines above:
The
elsebranch covers every non-Windows platform, not Linux. This is the same validation-asymmetry shape as thenuma_id/is_numa_currentsplit inHost— the correct check exists and the guard next to it doesn't use it.2. Exactly one function needs the library.
libcis used only formemcmp, incuda_core/tests/helpers/buffers.py(two call sites). Everything else the package exports —IS_WSL,IS_LINUX,IS_WINDOWS,under_compute_sanitizer,driver_version_less_than— is pure Python.3. It breaks collection, not just that helper.
cuda_core/tests/conftest.pyregisters this package as a pytest plugin:so an unloadable libc stops the whole cuda_core suite from being collected, including every test that never touches
libc.Fix
Try the glibc soname first — so the library resolved on the platforms CI runs on is bit-for-bit what it was before — and fall back to
ctypes.util.find_library("c"). If nothing loads, raise anOSErrornaming the platform and what was tried, rather than a raw dlopen dump.On a glibc host this is a no-op:
CDLL("libc.so.6")succeeds on the first candidate andfind_libraryis never called.Tests
cuda_python_test_helpershas no test directory today; this addscuda_python_test_helpers/tests/test_libc_loading.py:libcexposes a workingmemcmp(equal and differing inputs);test_import_survives_without_the_glibc_soname— monkeypatchesctypes.CDLLto reject"libc.so.6"and re-imports the package, simulating musl/macOS on any host. This is the regression test, and it fails onmainon a glibc runner too, so it has teeth in CI rather than only on my machine;The fixture restores the real
ctypes.CDLLand re-imports the package on teardown, so the reload does not leak into other tests.Not wired into CI: this new directory is not in any job's test paths. #2539 / #2548 / #2549 each add
toolshed/teststo the nightly tooling job with a byte-identical one-line change; extending that same line to pick this up would be trivial, but I left it out rather than create a four-way conflict on one line. Happy to fold it in whichever way you prefer.Verification
pytest cuda_python_test_helpers/tests→ 3 passed on macOS (the package imports only stdlib, so this runs natively).__init__.pyrestored fromupstream/main, the module cannot even be imported on macOS, so the test file fails at collection with theOSErrorabove. On a glibc host the meaningful teeth are intest_import_survives_without_the_glibc_soname, which fails there because the unconditionalCDLL("libc.so.6")raises under the simulated block.try/finallyharness (cpaside →git show upstream/main:<path> >→ run → restore infinally), so the working tree is put back even when the run under test fails. Index verified clean before committing.ruff check/ruff format --checkclean on both files.